#pragma once;
#include "baseutil.h"
#include <boost/scoped_array.hpp>
//TODO test it
//for bool/char/short/int/long etc, but not for classes!!

#include "SharedArray.h"
namespace yet{
template<typename T>
class Vector: public SharedArray<T> {
	typedef SharedArray<T> Super;
public:
	Vector(const T* values, int len) {
		assert(len>=0);
		if (values && len) {
			copyFrom(values, len);
		}
	}
	Vector(const T& val, int repeatCount) {
		assert(repeatCount>=0);
		if (repeatCount) {
			Super::init(repeatCount);
			Super::setLength(repeatCount);
			Super::fill(0, val);
		}
	}
	Vector(const vector<T>& vec) {
		if (!vec.empty()) {
			copyFrom(vec.begin(), vec.size());
		}
	}
	Vector(const Vector<T>& other) {
		Super::arr = other.arr;
		Super::count = other.count;
		Super::capcity = other.capcity;
	}
	explicit Vector(int capcity_) {
		assert(capcity_>=0);
		Super::init(capcity_);
	}
	Vector() {
	}
	virtual ~Vector() {
	}
public:

	Vector<T>& operator=(const Vector<T>& other) {
		Super::arr = other.arr;
		Super::count = other.count;
		Super::capcity = other.capcity;
		return *this;
	}

public:

	inline const T* begin() const {
		return beginR();
	}
	inline const T* end()  const{
		return endR();
	}
	inline  T* begin()  {
		return beginW();
	}
	inline  T* end()  {
		return endW();
	}

	 inline T* beginW() {
		maybeCloneSelf();
		return Super::getBufferWrite();
	}
	inline T* endW() {
		maybeCloneSelf();
		return Super::getBufferWrite() + length();
	}

	inline const T* beginR() const{
		return Super::getBufferRead();
	}
	inline const T* endR() const {
		return Super::getBufferRead() + length();
	}

	void removeIterator(T* pVal) {
		if (pVal && pValue >= begin() && pVal < end()) {
			int index = pVal - begin();
			remove(index);
		}
	}
	void removeValue(const T& val) {
		for (int i = 0; i < length(); ++i) {
			if (arr[i] == val) {
				remove(i);
				return;
			}
		}
	}
	void removeAllValues(const T& val) {
		for (int i = 0; i < length();) {
			if (arr[i] == val) {
				remove(i);
				continue;
			} else {
				++i;
			}
		}
	}

	Vector<T> clone() const {
		Vector<T> s(arr.get(), length());
		return s;
	}

	void setLength(int len) {
		assert(len>=0);
		assert( len <= capcity);
		Super::count = len;
	}

	inline void append(T val) {
		Super::replace(count, 0, &val, 1);
	}

	inline void append(const T* s, int len) {
		assert(len>=0);
		Super::replace(count, 0, s, len);
	}

	inline void insert(int index, T val) {
		assert(index>=0);
		Super::replace(index, 0, &val, 1);
	}
	inline void insert(int index, const T* s, int len) {
		assert(index>=0);
		assert(len>=0);
		Super::replace(index, 0, s, len);
	}

	void append(const Vector<T>& s) {
		replace(Super::count, 0, s);
	}
	void insert(int index, const Vector<T>& s) {
		assert(index>=0);
		replace(index, 0, s);
	}
	inline void replace(int from, int length, const Vector<T>& s) {
		assert(from>=0);
		assert(length>=0);
		Super::replace(from, length, s.arr.get(), s.length());
	}
	inline void replace(int from, int length, const T* values, int valuesCount) {
		assert(from>=0);
		assert(length>=0);
		assert(valuesCount>=0);
		Super::replace(from, length, values, valuesCount);
	}

	Vector<T> sub(int from, int length) const {
		assert(from>=0);
		assert(length>=0);
		assert(from + length <= Super::count);
		Vector<T> s(Super::arr.get() + from, length);
		return s;

	}

	Vector<T> sub(int from) const {
		assert(from>=0);
		assert(from < Super::count);
		int len = Super::count - from;
		return sub(from, len);
	}
	bool contains(const T& val) {
		for (int i = 0; i < length(); ++i) {
			if (getRef(i) == val) {
				return true;
			}
		}
		return false;
	}

	void getRange(Vector<T>& result, int from, int size) {
		assert(from>=0);
		assert(size>=0);
		assert(from+size <=length());
		result.clear();
		result.ensureCapcity(size);
		result.setLength(size);
		ArrayMove(result.getBufferWrite(), 0, getBufferRead(), from, size);
	}

	inline bool equals(const Vector<T>& other) const {
		if (this == &other) {
			return true;
		}
		return Super::equals(other.arr.get(), other.count);
	}
	inline bool equals(const T* other, int len) const {
		assert(len>=0);
		return Super::equals(other, len);
	}
}
;
class IntVector: public Vector<int> {
public:
	explicit IntVector(int capcity_ = 8)
			: Vector<int>(capcity_) {
	}
	//[from, to)
	void rangeAdd(int from, int to, int delta) {
		assert(from>=0);
		assert(to>=0);
		assert( from < size() && to <= size());
		for (int i = from; i < to; ++i) {
			getRef(i) += delta;
		}
	}
};

}
